<!DOCTYPE html>
<html>
    <head lang="en">
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, initial-scale=1.0, maximum-scale=1.2, user-scalable=no" />
        <title>架构图Demo</title>
        <style type='text/css'>
            html, body{
                font-family:"Microsoft YaHei", "Arial", "黑体", "宋体", sans-serif;
                background:#FFFFFF;
                height:100%;
                font-size:14px;
            }

            ul, ol{
                list-style:none;
            }

            *{
                margin:0;
                padding:0;
                box-sizing:border-box;
            }

            .target-wrap{
                overflow:auto;
                width:100%;
                height:100%;
            }

            .target-container{
                position:relative;
            }

            .target-content{
                position:absolute;
                left:0;
                top:0;
                z-index:2;
                backgroud:transparent;
                min-width:100%;
            }

            .line-canvas{
                position:absolute;
                top:0;
                left:0;
                z-index:1;
            }

            .target-wrap{
                min-width:100%;
            }

            .target-list{
                display:flex;
                align-items:center;
                justify-content:space-around;
                flex-wrap:nowrap;
                min-width:100%;
                margin:40px 0 50px;
            }

            .target-item{
                background:#F2F7FC;
                border:1px solid #CCCCCC;
                color:#3D6CEE;
                font-size:16px;
                padding:10px 10px;
                line-height:1.5;
                border-radius:10px;
                margin:0 15px;
                min-width:150px;
                text-align:center;
                cursor:pointer;
                user-select:none;
            }

            .target-detail{
                background:rgba(0, 0, 0, 0.5);
                color:#FFFFFF;
                position:absolute;
                top:50%;
                right:10px;
                padding:0 20px 20px;
                transform:translateY(-50%);
                z-index:2;
                max-width:30%;
                max-height:90%;
                overflow-x:hidden;
                overflow-y:auto;
            }

            .attr-title{
                font-size:16px;
                font-weight:bold;
                padding:20px 0;
            }

            .attr-item{
                margin:0 0 5px;
            }

            .attr-value{
                font-weight:bold;
            }

            .base-attr-list{
                padding:0 0 20px;
                border-bottom:1px solid #CCCCCC;
            }
        </style>
    </head>
    <body>
    <div class='target-container' id="targetContainer">
        <div class="target-wrap">
            <canvas id="lineCanvas" class="line-canvas">
                当前浏览器不支持Canvas，请更换浏览器后再试
            </canvas>
            <div class='target-content' id="targetContent"></div>
        </div>
        <div class="target-detail" id="targetDetail">
            <p class="attr-title">基本属性</p>
            <ul class="base-attr-list" id="baseAttrList"></ul>
            <p class="attr-title">自定义属性</p>
            <ul class="customize-attr-list" id="customizeAttrList"></ul>
        </div>
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script>
		//指标数组
		var targetArr = [
			{
				targetId:1,
				targetName:'企业主体信用得分',
				pid:[],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'企业主体信用得分'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:2,
				targetName:'机动能力指标',
				pid:[1],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'机动能力指标'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:3,
				targetName:'打击能力指标',
				pid:[1],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'打击能力指标'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:4,
				targetName:'基本信息',
				pid:[2],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'基本信息'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:5,
				targetName:'管理认证',
				pid:[2,3],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'管理认证'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:6,
				targetName:'税务执行情况',
				pid:[2,3],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'税务执行情况'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:7,
				targetName:'网贷情况',
				pid:[3],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'网贷情况'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:8,
				targetName:'网贷情况8',
				pid:[3],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'网贷情况8'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
			{
				targetId:9,
				targetName:'网贷情况9',
				pid:[3],
				baseAttr:[
					{
						attrName:'指标名称',
						value:'网贷情况9'
					},
					{
						attrName:'指标单位',
						value:'指标单位'
					},
					{
						attrName:'指标类型',
						value:'时间型'
					},
					{
						attrName:'指标描述',
						value:'逗比指标'
					},
				],
				customizeAttr:[
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
					{
						attrName:'侦查处理速率',
						value:'100bps'
					},
				]
			},
		];
		//渲染数组
		var renderArr = [];
		//线宽度
		var lineWidth = 1;
		//线颜色
		var strokeStyle = '#ccc';
		var canvas;
		var context;
		//获取渲染单行数据
		var getRenderItem = function(pid){
			let renderItem = []
			for(var i in targetArr){
				var item = targetArr[i]
				if(pid.length == 0 && item.pid.length == 0){
					renderItem.push(item)
					continue
				}
				for(var j in item.pid){
					if(pid.indexOf(item.pid[j]) != '-1'){
						renderItem.push(item)
						break
					}
				}
			}
			if(renderItem.length){
				renderArr.push(renderItem)
			}
			let idList = []
			for(var j in renderItem){
				idList.push(renderItem[j].targetId)
			}
			if(idList.length){
				getRenderItem(idList)
			}
		}
		//渲染指标数据
		var renderTarget = function(){
			var html = '';
			for(var i in renderArr){
				var rowItem = renderArr[i];
				html += '<ul class="target-list">';
				for(var j in rowItem){
					var colItem = rowItem[j];
					var targetId = colItem.targetId;
					var targetName = colItem.targetName;
					html += '<li class="target-item" targetId="' + targetId + '">' + targetName + '</li>';
				}
				html += '</ul>';
			}
			$('#targetContent').append(html)
		}
		//初始化画布
		var initCanvas = function(){
			canvas = document.getElementById("lineCanvas");
			$('.target-wrap').width($('.target-content').width())
			$('.target-wrap').height($('.target-content').height())
			context = canvas.getContext("2d")
			//画布缩放处理斜线毛边
			var width = parseInt($('.target-content').width()),height = parseInt($('.target-content').height());
			canvas.style.width = width + "px";
			canvas.style.height = height + "px";
			canvas.height = height * 4;
			canvas.width = width * 4;
			context.scale(4,4);
		}
		//画线
		var drawLine = function(a,b){
			context.beginPath();
			context.moveTo(formatPosition(a.top.x),formatPosition(a.top.y));
			context.lineTo(formatPosition(b.bottom.x),formatPosition(b.bottom.y));
			context.lineWidth = lineWidth;
			context.strokeStyle = strokeStyle;
			context.stroke();
		}
		//线去毛边处理
		var formatPosition = function(position){
			return parseInt(position) + 0.5
		}
		//获取连线点位置
		var getPointPosition = function(targetId){
			var result = {
				top:{},
				bottom:{}
			}
			var targetContainer = $('#targetContainer')[0]
			var $colItemEl = $('[targetId=' + targetId + ']')[0]
			result.top.x = $colItemEl.offsetLeft + ($colItemEl.offsetWidth / 2) + targetContainer.offsetLeft
			result.top.y = $colItemEl.offsetTop + targetContainer.offsetTop
			result.bottom.x = $colItemEl.offsetLeft + ($colItemEl.offsetWidth / 2) + targetContainer.offsetLeft
			result.bottom.y = $colItemEl.offsetTop + $colItemEl.offsetHeight + targetContainer.offsetTop
			return result
		}
		//连线
		var connection = function(){
			for(var i in renderArr){
				var rowItem = renderArr[i];
				for(var j in rowItem){
					var colItem = rowItem[j];
					if(colItem.pid.length){
						var pid = colItem.pid
						var targetId = colItem.targetId
						var itemPosition = getPointPosition(targetId)
						for(var z in pid){
							var parentPosition = getPointPosition(pid[z])
							drawLine(itemPosition,parentPosition)
						}
					}
				}
			}
		}
		//根据ID 获取target
		var getTargetById = function(targetId){
			for(var i in targetArr){
				if(targetId == targetArr[i].targetId){
					return targetArr[i]
				}
			}
			return ''
		}
		//渲染属性列表
		var renderAttrList = function(el,attrList){
            var html = ''
            for(var i in attrList){
				var attr = attrList[i]
            	html += '<li class="attr-item">'
            	html += '<lable class="attr-name">'+attr.attrName+'：</lable>'
            	html += '<span class="attr-value">'+attr.value+'</span>'
            	html += '</li>'
            }
			el.append(html)
		}
		//渲染target 弹窗数据
		var renderTargetDetail = function(targetId){
			var targetItem = getTargetById(targetId)
			var baseAttr = targetItem.baseAttr
			var customizeAttr = targetItem.customizeAttr
			var $baseAttrList = $('#baseAttrList')
			var $customizeAttrList = $('#customizeAttrList')
			$baseAttrList.empty()
			$customizeAttrList.empty()
			renderAttrList($baseAttrList,baseAttr)
			renderAttrList($customizeAttrList,customizeAttr)
		}
		
		//详情弹出
		$(document).click(function(){
			$('#targetDetail').hide();
		})
		$(document).on('click','#targetDetail',function(e){
			e.stopPropagation()
		})
		$(document).on('click','.target-item',function(e){
			e.stopPropagation()
			$('#targetDetail').show();
			var targetId = $(this).attr('targetId')
			renderTargetDetail(targetId)
		})

		getRenderItem([])
		renderTarget()
		initCanvas()
		connection()
		renderTargetDetail(targetArr[0].targetId)
		window.onresize = function(){
			initCanvas()
			connection()
		}
    </script>
    </body>
</html>